import { HttpException, Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import Axios from 'axios';
import { EntityManager } from 'typeorm';
import { LoginByPhoneDto } from './dto/login.dto';
import { UpdatePhoneDto } from './dto/update-phone.dto';

@Injectable()
export class AuthService {
  constructor(
    private readonly jwtService: JwtService,
    private readonly em: EntityManager,
  ) {}

  async getTokenByWxapp(wechatOpenId: string) {
    const user = await this.em
      .getRepository('User')
      .findOneBy({ wechatOpenId });
    if (user && user.phone) {
      const payload = {
        userId: user.id,
      };
      return {
        ...user,
        accessToken: await this.jwtService.signAsync(payload),
      };
    }
    throw new HttpException('用户不存在', 404);
  }

  async signInByPhone(signInDto: LoginByPhoneDto) {
    const { phone, code } = signInDto;
    const sms = await this.em.getRepository('Sms').findOneBy({ phone, code });
    if (!sms) throw new HttpException('验证码错误', 400);
    // 验证码更新时间距离现在超过5分钟，视为验证码失效
    if (sms.updatedAt + 5 * 60 * 1000 < Date.now()) {
      throw new HttpException('验证码已过期', 400);
    }
    let user = await this.em.getRepository('User').findOneBy({ phone });
    if (!user) {
      // 用户不存在，创建新用户
      user = await this.em.getRepository('User').save({
        phone,
      });
    }
    if (user.isFrozen) throw new HttpException('账号已冻结', 403);
    const payload = {
      userId: user.id,
    };

    return {
      ...user,
      accessToken: await this.jwtService.signAsync(payload),
    };
  }

  async updatePhone(updatePhoneDto: UpdatePhoneDto, wxOpenID: string) {
    const api = `http://api.weixin.qq.com/wxa/getopendata?openid=${wxOpenID}`;
    const res: any = await Axios({
      method: 'post',
      url: api,
      data: {
        cloudid_list: [updatePhoneDto.cloudid],
      },
      headers: {
        'Content-Type': 'application/json',
      },
    });
    const data_list = res.data?.data_list;
    if (data_list.length === 0) {
      throw new HttpException('微信获取手机号失败', 400);
    }
    let phone;
    try {
      const data = JSON.parse(data_list[0].json);
      phone = data.data?.phoneNumber;
    } catch {
      throw new HttpException('手机号格式解析失败', 400);
    }
    if (!phone) {
      throw new HttpException('微信获取手机号为空', 400);
    }
    // 通过手机号获取用户
    const phoneUser = await this.em.getRepository('User').findOneBy({
      phone,
    });
    if (phoneUser) {
      // 判断手机号是否绑定微信openid
      if (phoneUser.wechatOpenId) {
        // 判断微信openid是否一致
        if (phoneUser.wechatOpenId === wxOpenID) {
          const payload = {
            userId: phoneUser.id,
          };
          const token = await this.jwtService.signAsync(payload);
          return {
            ...phoneUser,
            accessToken: token,
          };
        }
        throw new HttpException('该手机号已绑定其他微信号', 400);
      }
      // 绑定微信openid
      await this.em
        .getRepository('User')
        .update({ id: phoneUser.id }, { wechatOpenId: wxOpenID });
      const payload = {
        userId: phoneUser.id,
      };
      const token = await this.jwtService.signAsync(payload);
      return {
        ...phoneUser,
        accessToken: token,
      };
    } else {
      // 没有找到相关手机号用户，创建新用户
      const newUser = await this.em.getRepository('User').save({
        phone,
        wechatOpenId: wxOpenID,
      });
      const payload = {
        userId: newUser.id,
      };
      const token = await this.jwtService.signAsync(payload);
      return {
        ...newUser,
        accessToken: token,
      };
    }
  }
}
